﻿using System;
using System.Runtime.InteropServices;

namespace Recast
{
    public static class NavMeshInterface
    {
        /// <summary>
        /// NavMesh
        /// </summary>
        /// <returns></returns>
        [DllImport("xlua")]
        public static extern IntPtr AllocNavMesh();

        [DllImport("xlua")]
        public static extern IntPtr LoadNavMesh(byte[] buf, int length);

        [DllImport("xlua")]
        public static extern void FreeNavMesh(IntPtr ptr);

        /// <summary>
        /// NavMeshQuery
        /// </summary>
        /// <returns></returns>

        [DllImport("xlua")]
        public static extern IntPtr AllocNavMeshQuery();

        [DllImport("xlua")]
        public static extern bool InitNavMeshQuery(IntPtr query, IntPtr mesh, int maxNodes);

        [DllImport("xlua")]
        public static extern void FreeNavMeshQuery(IntPtr query);

        [DllImport("xlua")]
        public static extern uint FindNearestPoly(IntPtr query, float[] center, float[] halfExtents,
                IntPtr filter,
                out uint nearestRef,float[] nearestPt);

        /// <summary>
        /// navmesh filter
        /// </summary>
        /// <returns></returns>

        [DllImport("xlua")]
        public static extern IntPtr AllocNavMeshQueryFilter();

        [DllImport("xlua")]
        public static extern void SetAreaCost(IntPtr queryFilter, int i, float cost);

        [DllImport("xlua")]
        public static extern void SetIncludeFlags(IntPtr queryFilter, int flags);

        [DllImport("xlua")]
        public static extern void SetExcludeFlags(IntPtr queryFilter, int flags);

        [DllImport("xlua")]
        public static extern void FreeNavMeshQueryFilter(IntPtr queryFilter);

        // Returns true of status is success.
        public static bool Succeed(this uint status)
        {
            return (status & Status.DT_SUCCESS) != 0;
        }

        // Returns true of status is failure.
        public static bool Failed(this uint status)
        {
            return (status & Status.DT_FAILURE) != 0;
        }

        // Returns true of status is in progress.
        public static bool InProgress(this uint status)
        {
            return (status & Status.DT_IN_PROGRESS) != 0;
        }

        // Returns true if specific detail is set.
        public static bool HasDetail(this uint status, uint detail)
        {
            return (status & detail) != 0;
        }

        /// <summary>
        /// C++ Log 2 Unity
        /// </summary>
        /// <param name="message"></param>
        /// <param name="iSize"></param>
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void LogDelegate(IntPtr message, int iSize);
        [DllImport("xlua", CallingConvention = CallingConvention.Cdecl)]
        static extern void SetupLogDelegate(LogDelegate log);

        //C# Function for C++‘s call
        [AOT.MonoPInvokeCallback(typeof(LogDelegate))]
        static void LogCB(IntPtr message, int iSize)
        {
            UnityEngine.Debug.Log(Marshal.PtrToStringAnsi(message, iSize));
        }

        public static void SetupLog()
        {
            SetupLogDelegate(LogCB);
        }
    }
}